﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace TiaoTiaoCode.Common.Extensions
{
    /// <summary>
    /// 进制转换扩展
    /// </summary>
    public static class DigitConvertEx
    {
        #region 进制转换

        /// <summary>
        /// byte 转十六进制
        /// </summary>
        /// <param name="b"></param>
        /// <returns></returns>
        public static string TiaoTiaoToHex(this byte b)
        {
            return b.ToString("X2");
        }

        /// <summary>
        /// byte流转十六进制串
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="span"></param>
        /// <returns></returns>
        public static string TiaoTiaoToHexString(this IEnumerable<byte> bytes, string span = "")
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (byte @byte in bytes)
            {
                stringBuilder.Append(@byte.ToString("X").PadLeft(2, '0'));
                stringBuilder.Append(span);
            }

            return stringBuilder.ToString();
        }

        /// <summary>
        /// 字符串转十六进制
        /// </summary>
        /// <param name="str"></param>
        /// <param name="span"></param>
        /// <returns></returns>
        public static byte[] TiaoTiaoToHexBytes(this string str, string span = "")
        {
            if (str.TiaoTiaoIsNotNullOrEmpty())
            {
                str = str.Replace(span, "");
            }

            if (str.TiaoTiaoIsNullOrEmpty())
            {
                return new byte[0];
            }

            byte[] array = new byte[str.Length / 2];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = byte.Parse(str.Substring(2 * i, 2), NumberStyles.AllowHexSpecifier);
            }

            return array;
        }

        /// <summary>
        /// 转二进制字符串
        /// </summary>
        /// <param name="i"></param>
        /// <param name="stringLen">字符串长度</param>
        /// <returns></returns>
        public static string TiaoTiaoToBinString(this int i, int stringLen = 8)
        {
            return Convert.ToString(i, 2).PadLeft(stringLen, '0');
        }

        /// <summary>
        /// 转二进制字符串
        /// </summary>
        /// <param name="i"></param>
        /// <param name="stringLen">字符串长度</param>
        /// <returns></returns>
        public static string TiaoTiaoToBinString(this byte i, int stringLen = 4)
        {
            return Convert.ToString(i, 2).PadLeft(stringLen, '0');
        }

        #endregion

        #region 数字转百分比

        /// <summary>
        /// 小数转百分比
        /// </summary>
        /// <param name="d"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string TiaoTiaoToPercent(this decimal? d, string defaultValue = "")
        {
            if (d == null) return defaultValue;

            var length = TiaoTiaoGetPointOfNumber(d);
            if (length >= 2)
            {
                string temp = "P" + (length - 2).ToString();
                return ((decimal)d).ToString(temp);
            }
            else
                return ((int)(d * 100)).ToString() + "%";
        }

        /// <summary>
        /// 小数转百分比
        /// </summary>
        /// <param name="d"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string TiaoTiaoToPercent(this float? d, string defaultValue = "")
        {
            if (d == null) return defaultValue;

            var length = TiaoTiaoGetPointOfNumber(d);
            if (length >= 2)
            {
                string temp = "P" + (length - 2).ToString();
                return ((decimal)d).ToString(temp);
            }
            else
                return ((int)(d * 100)).ToString() + "%";
        }

        /// <summary>
        /// 小数转百分比
        /// </summary>
        /// <param name="d"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string TiaoTiaoToPercent(this double? d, string defaultValue = "")
        {
            if (d == null) return defaultValue;

            var length = TiaoTiaoGetPointOfNumber(d);
            if (length >= 2)
            {
                string temp = "P" + (length - 2).ToString();
                return ((decimal)d).ToString(temp);
            }
            else
                return ((int)(d * 100)).ToString() + "%";
        }

        /// <summary>
        /// 小数转百分比
        /// </summary>
        /// <param name="d"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string TiaoTiaoToPercent(this int? d, string defaultValue = "")
        {
            if (d == null) return defaultValue;

            return ((int)(d * 100)).ToString() + "%";
        }

        /// <summary>
        /// 获取小数点位数
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static int TiaoTiaoGetPointOfNumber(this double? d)
        {
            if (d == null) return 0;

            var s = d.ToString();
            return s.Length - s.IndexOf('.') - 1;
        }

        /// <summary>
        /// 获取小数点位数
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static int TiaoTiaoGetPointOfNumber(this float? d)
        {
            if (d == null) return 0;

            var s = d.ToString();
            return s.Length - s.IndexOf('.') - 1;
        }

        /// <summary>
        /// 获取小数点位数
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static int TiaoTiaoGetPointOfNumber(this decimal? d)
        {
            if (d == null) return 0;

            var s = d.ToString();
            return s.Length - s.IndexOf('.') - 1;
        }

        #endregion

        #region

        /// <summary>
        /// 是否在范围内
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool TiaoTiaoInRange<T>(this T value, T minValue, T maxValue) where T : IComparable
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (minValue.CompareTo(maxValue) == 1)
            {
                T val = minValue;
                minValue = maxValue;
                maxValue = val;
            }

            return value.CompareTo(minValue) >= 0 && value.CompareTo(maxValue) <= 0;
        }

        #endregion
    }
}
